
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

import Messaging.IMessage;
import Messaging.BTCommand;
import Messaging.Hit;
import Messaging.Life;
import Messaging.Loss;
import Messaging.Stamina;
import Messaging.Win;
import lejos.pc.comm.NXTComm;
import lejos.pc.comm.NXTCommFactory;
import lejos.pc.comm.NXTInfo;
import lejos.util.Delay;
import Messaging.*;

public class CommunicateThread extends
		SwingWorker<Void, CommunicateThread.GUIVals> {
	static class GUIVals {
		public GUIVals(Integer l, Integer s) {
			Life = l;
			Stamina = s;
		}

		public GUIVals(String name) {
			Name = name;
		}

		public Integer Life;
		public Integer Stamina;
		public String Name;
	}

	private int left = 0, right = 0;
	private boolean sendValueNow = false;

	private String name;
	private String address;

	private NXTComm nxtComm;
	private NXTInfo nxtInfo;
	private DataOutputStream dos;

	private DataInputStream dis;
	private ArrayBlockingQueue<IMessage> messageQueue;
	private ArrayBlockingQueue<Hit> hitQueue;
	private JProgressBar life;
	private JProgressBar stamina;
	private JLabel GUIname;
	private BTReceive receiveThread;
	private ArrayBlockingQueue<IMessage> otherQueue;

	public CommunicateThread(ArrayBlockingQueue<IMessage> _queue,
			ArrayBlockingQueue<IMessage> otherQueue, JLabel GUIname,
			JProgressBar life, JProgressBar stamina,
			ArrayBlockingQueue<Hit> hitQueue, String _name, String _address) {
		messageQueue = _queue;
		name = _name;
		address = _address;
		this.hitQueue = hitQueue;
		this.life = life;
		this.stamina = stamina;
		this.GUIname = GUIname;
		this.otherQueue = otherQueue;
	}

	@Override
	protected Void doInBackground() {
		//JOptionPane.showMessageDialog(null, name+" "+Thread.currentThread().getId());
		
		Connect();
		IMessage message = null;
		messageQueue.add(new Name());

		receiveThread = new BTReceive(dis);
		receiveThread.start();

		long time = System.currentTimeMillis();

		while (true) {
			try {
				if (!messageQueue.isEmpty())
					write(message);
				read();
			} catch (Exception e) {

			}
			if (System.currentTimeMillis() > time + 1000) {
				time = System.currentTimeMillis();
				messageQueue.add(new Life());
				messageQueue.add(new Stamina());
			}

			Delay.msDelay(20);
		}

	}

	private void read() throws IOException {
		if (receiveThread.Available()) {
			String command = receiveThread.getCommand();

			switch (command.charAt(0)) {
			case BTCommand.HIT:
				hitQueue.add(new Hit(name));
				break;

			case BTCommand.LIFE:
				int life = Integer.parseInt(command.substring(1));
				if (life <= 0) {
					messageQueue.add(new Loss());
					otherQueue.add(new Win());
				}

				publish(new GUIVals(life, -1));
				break;

			case BTCommand.STAMINA:
				int stam = Integer.parseInt(command.substring(1));
				publish(new GUIVals(-1, stam));
				break;
			case BTCommand.NAME:
				String name = command.substring(1);
				publish(new GUIVals(name));
				break;

			default:
				break;
			}
		}
	}

	private void write(IMessage message) throws InterruptedException,
			IOException {
		message = messageQueue.take();
		if (message != null) {
			dos.writeInt(message.GetLength());
			dos.write(message.GetCommand());
			dos.flush();
		}
	}

	private void Connect() {
		nxtInfo = new NXTInfo();
		nxtInfo.name = name;
		nxtInfo.deviceAddress = address;
		try {

			nxtComm = NXTCommFactory.createNXTComm(NXTCommFactory.BLUETOOTH);
			nxtComm.open(nxtInfo);
			dos = new DataOutputStream(nxtComm.getOutputStream());
			dis = new DataInputStream(nxtComm.getInputStream());
		} catch (Exception ex) {
		}
	}

	@Override
	protected void process(final List<GUIVals> chunks) {
		if (chunks.get(0).Life != null && chunks.get(0).Life != -1)
			life.setValue(chunks.get(0).Life);
		if (chunks.get(0).Stamina != null && chunks.get(0).Stamina != -1)
			stamina.setValue(chunks.get(0).Stamina);
		if (chunks.get(0).Name != null)
			GUIname.setText(chunks.get(0).Name);
	}

}
